<?php

namespace Hilaoyu\Utils;

use Graze\GuzzleHttp\JsonRpc\Client;
use Hilaoyu\Utils\Traits\ErrorsTrait;

class UtilRpcClient
{
    public static function make(string $uri,string $secret=null){
        return new static($uri,$secret);
    }

    use ErrorsTrait;
    protected $rpcClient;
    protected $encryptor;
    public function __construct(string $uri,string $secret=null)
    {
        $this->rpcClient = Client::factory($uri,["headers"=>['X-JSONRPC-2.0'=>'true']]);
        if("" != $secret){
            $this->encryptor = UtilAes::make($secret);
        }

    }

    public function generateRpcId(){
        $id = UtilStr::replace(microtime(true),['.'=>'']);
        $id .= rand(0,1000);
        return $id;
    }



    public function request(string $rpcMethod,array $params = null){

        $req = $this->rpcClient->request($this->generateRpcId(),$rpcMethod,$this->encryptParams($params));
        $response = $this->rpcClient->send($req);
        $errors = $response->getRpcErrorMessage();
        if(!empty($errors)){
            $this->setError($errors);
        }
        //return $response->getRpcResult();
        return $this->decryptResult($response->getRpcResult());
    }

    /**
     * @param string $rpcMethod
     * @param array|null $params
     * @return \GuzzleHttp\Promise\PromiseInterface
     *
     * $p =UtilRpc::make("127.0.0.1:12201")->requestAsync("test.Hello",["data"=>"sadasfaf"]);
    $p->then(function ($data){
    dump("data",$data);
    });



    dump("p",$p);
    $p->wait();
     */
    public function requestAsync(string $rpcMethod,array $params = null){

        $req = $this->rpcClient->request($this->generateRpcId(),$rpcMethod,$this->encryptParams($params));
        $promise = $this->rpcClient->sendAsync($req);
        return $promise->then(function ($response) {
            $errors = $response->getRpcErrorMessage();
            if(!empty($errors)){
                $this->setError($errors);
            }
            //return $response->getRpcResult();
            return $this->decryptResult($response->getRpcResult());
        });

    }


    protected function encryptParams(array $params = null){
        if(empty($params)){
            return $params;
        }
        if($this->encryptor){
            $params['timestamp'] = time();
            $params['_data_id'] = $this->generateRpcId();
            $params = ['data'=>$this->encryptor->encrypt($params)];
        }
        return $params;
    }
    protected function decryptResult($result){
        if(empty($result)){
            return $result;
        }
        if($this->encryptor){
            $result = $this->encryptor->decrypt(UtilArr::get($result,'data'),true);
        }
        return $result;
    }
}
